cmake_minimum_required(VERSION 2.6)
PROJECT(intrinsic-noise-analyzer)


#
# Register own CMake extensions:
#
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${PROJECT_SOURCE_DIR}/cmake)
include(InstallHeadersWithDirectory)

#
# Define some options
#
OPTION(INA_ENABLE_VERSION_CHECK "Enables the periodic check about a new version of iNA" OFF)
OPTION(INA_ENABLE_OPENMP "Enables OpenMP support" ON)
OPTION(INA_ENABLE_STATIC "Enables static compilation" OFF)
OPTION(INA_BUILD_UNITTEST "Enables build of unit tests explicitly." OFF)
OPTION(WITH_LLVM_CONFIG "Specifies the LLVM config executable to be used (needed for MacPorts)" OFF)
OPTION(WITH_INA_GUI "Specifies if the iNA GUI is compiled (defalut: ON)" ON)

# Disable version check on debug builds:
IF(CMAKE_BUILD_TYPE MATCHES DEBUG)
 SET(INA_ENABLE_NEW_VERSION_CHECK OFF)
 SET(INA_BUILD_UNITTEST ON)
ENDIF(CMAKE_BUILD_TYPE MATCHES DEBUG)


#
# Get default directories under Linux
#
IF(UNIX AND NOT APPLE)
INCLUDE(GNUInstallDirs)
ELSE()
SET(CMAKE_INSTALL_LIBDIR "lib")
SET(CMAKE_INSTALL_FULL_LIBDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
SET(CMAKE_INSTALL_INCLUDEDIR "include")
SET(CMAKE_INSTALL_FULL_INCLUDEDIR "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}")
# Set RPATH under MacOS
SET(CMAKE_SKIP_BUILD_RPATH  FALSE)
SET(CMAKE_INSTALL_RPATH "${CMAKE_INSTALL_PREFIX}/lib")
SET(CMAKE_BUILD_WITH_INSTALL_RPATH FALSE)
#SET(CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS} "--std=c++98 --stdlib=libc++")
#SET(LIBS ${LIBS} "c++")
ENDIF(UNIX AND NOT APPLE)

#
# Search for libraries
#
FIND_PACKAGE(Qt4 REQUIRED)
SET(QT_USE_QTSVG TRUE)
SET(QT_USE_QTNETWORK TRUE)
INCLUDE(${QT_USE_FILE})
ADD_DEFINITIONS(${QT_DEFINITIONS})
INCLUDE_DIRECTORIES(${QT_QTCORE_INCLUDE_DIR} ${QT_QTGUI_INCLUDE_DIR})

IF(NOT INA_ENABLE_STATIC)
FIND_PACKAGE(Eigen3 REQUIRED)
FIND_PACKAGE(Ginac REQUIRED)
FIND_PACKAGE(LibSBML REQUIRED)
FIND_PACKAGE(LLVM REQUIRED)
IF(INA_ENABLE_OPENMP)
  SET(OpenMP_C_FLAGS "-fopenmp")
  SET(OpenMP_CXX_FLAGS "-fopenmp")
  SET(OPENMP_LIBRARIES pthread gomp)
ENDIF(INA_ENABLE_OPENMP)
ENDIF(NOT INA_ENABLE_STATIC)

# Specify iNA version, will be used in config.hh, package name and library suffix.
SET(INA_VERSION_MAJOR 0)
SET(INA_VERSION_MINOR 4)
SET(INA_VERSION_PATCH 3)

# Make sure libina can be found
LINK_DIRECTORIES(${PROJECT_BINARY_DIR}/lib)
INCLUDE_DIRECTORIES("${PROJECT_BINARY_DIR}/include/libina")
#INCLUDE_DIRECTORIES("${PROJECT_SOURCE_DIR}/lib")

#
# Used libaries:
#
IF(INA_ENABLE_STATIC)
 # make sure you have them
 LINK_DIRECTORIES("/opt/lib")
 set(LIBS ${LIBS} ginac cln gmp sbml xml2 z bz2 m pthread gomp)
ELSE()
 set(LIBS ${LIBS} ${GINAC_LIBRARIES} ${LIBSBML_LIBRARIES} ${OPENMP_LIBRARIES} m)
 LINK_DIRECTORIES(${LLVM_LIB_DIR})
ENDIF(INA_ENABLE_STATIC)

#
# Used headers:
#
INCLUDE_DIRECTORIES(${EIGEN3_INCLUDE_DIRS} ${GINAC_INCLUDE_DIRS} ${LIBSBML_INCLUDE_DIRS} ${LLVM_INCLUDE_DIRS})

#
# Compiler flags:
#

SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS} -Wall -frtti -fexceptions -Wno-unknown-pragmas")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} ${OpenMP_CXX_FLAGS} -O0 -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} ${OpenMP_CXX_FLAGS} -O2")

set(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} ${OpenMP_CXX_FLAGS})
set(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS_INIT} ${OpenMP_CXX_FLAGS})
set(CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS_INIT} ${OpenMP_CXX_FLAGS})

IF(INA_ENABLE_STATIC)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -static -fopenmp")
    set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -static -fopenmp")
    set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -static -fopenmp")
ENDIF()

# Let application start in its own window
IF(WIN32)
    SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mwindows")
ENDIF(WIN32)

#
# eigen + mingw weirdness, see
# http://eigen.tuxfamily.org/dox/TopicWrongStackAlignment.html
#
IF(WIN32 AND WINGW)
    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mincoming-stack-boundary=2")
    SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -mincoming-stack-boundary=2")
    SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -mincoming-stack-boundary=2 -mwindows")

    SET(CMAKE_EXE_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} -mincoming-stack-boundary=2)
    SET(CMAKE_SHARED_LINKER_FLAGS ${CMAKE_SHARED_LINKER_FLAGS} -mincoming-stack-boundary=2)
    SET(CMAKE_MODULE_LINKER_FLAGS ${CMAKE_MODULE_LINKER_FLAGS} -mincoming-stack-boundary=2)
ENDIF(WIN32 AND WINGW)

#
# Define flags, libs etc if LLVM is present:
#
IF(LLVM_FOUND AND NOT INA_ENABLE_STATIC)
MESSAGE(STATUS "LLVM support: yes, version: ${LLVM_VERSION}" )
SET(WITH_EXECUTION_ENGINE_LLVM ON)
SET(LIBS ${LIBS} ${LLVM_LIBRARIES})
INCLUDE_DIRECTORIES(${LLVM_INCLUDE_DIRS})
ADD_DEFINITIONS(-D_DEBUG -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LLVM_LD_FLAGS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${LLVM_LD_FLAGS}")
set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} ${LLVM_LD_FLAGS}")

# Handle LLVM version:
if((LLVM_VERSION VERSION_GREATER 2.8 OR LLVM_VERSION VERSION_EQUAL 2.8) AND (LLVM_VERSION VERSION_LESS 3.0))
set(INA_LLVM_VERSION_IS_2X ON)
set(INA_LLVM_VERSION_IS_3X OFF)
set(INA_LLVM_VERSION_IS_32 OFF)
set(INA_LLVM_VERSION_IS_31 OFF)
set(INA_LLVM_VERSION_IS_33 OFF)
endif((LLVM_VERSION VERSION_GREATER 2.8 OR LLVM_VERSION VERSION_EQUAL 2.8) AND (LLVM_VERSION VERSION_LESS 3.0))

if(LLVM_VERSION VERSION_GREATER 3.0 OR LLVM_VERSION VERSION_EQUAL 3.0)
set(INA_LLVM_VERSION_IS_2X OFF)
set(INA_LLVM_VERSION_IS_3X ON)
set(INA_LLVM_VERSION_IS_31 OFF)
set(INA_LLVM_VERSION_IS_32 OFF)
set(INA_LLVM_VERSION_IS_33 OFF)
endif(LLVM_VERSION VERSION_GREATER 3.0 OR LLVM_VERSION VERSION_EQUAL 3.0)

if(LLVM_VERSION VERSION_GREATER 3.1 OR LLVM_VERSION VERSION_EQUAL 3.1)
set(INA_LLVM_VERSION_IS_2X OFF)
set(INA_LLVM_VERSION_IS_3X ON)
set(INA_LLVM_VERSION_IS_31 ON)
set(INA_LLVM_VERSION_IS_32 OFF)
set(INA_LLVM_VERSION_IS_33 OFF)
endif(LLVM_VERSION VERSION_GREATER 3.1 OR LLVM_VERSION VERSION_EQUAL 3.1)

if(LLVM_VERSION VERSION_GREATER 3.2 OR LLVM_VERSION VERSION_EQUAL 3.2)
set(INA_LLVM_VERSION_IS_2X OFF)
set(INA_LLVM_VERSION_IS_3X ON)
set(INA_LLVM_VERSION_IS_31 OFF)
set(INA_LLVM_VERSION_IS_32 ON)
set(INA_LLVM_VERSION_IS_33 OFF)
endif(LLVM_VERSION VERSION_GREATER 3.2 OR LLVM_VERSION VERSION_EQUAL 3.2)

if(LLVM_VERSION VERSION_GREATER 3.3 OR LLVM_VERSION VERSION_EQUAL 3.3)
set(INA_LLVM_VERSION_IS_2X OFF)
set(INA_LLVM_VERSION_IS_3X ON)
set(INA_LLVM_VERSION_IS_31 OFF)
set(INA_LLVM_VERSION_IS_32 OFF)
set(INA_LLVM_VERSION_IS_33 ON)
endif(LLVM_VERSION VERSION_GREATER 3.3 OR LLVM_VERSION VERSION_EQUAL 3.3)


else()
MESSAGE(STATUS "LLVM support: no")
SET(WITH_EXECUTION_ENGINE_LLVM OFF)
ENDIF()


#
# Generate configuration header file, and ensure, it can be found...
#
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/lib/config.hh.in
               ${CMAKE_CURRENT_BINARY_DIR}/lib/config.hh)
CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/lib/config.hh.in
               ${PROJECT_BINARY_DIR}/include/libina/config.hh)

#
# Make sure unsupported module headers can be found
#
INCLUDE_DIRECTORIES(${PROJECT_SOURCE_DIR}/unsupported)

# Some messages summarizing the configuration
MESSAGE(STATUS "Build type: ${CMAKE_BUILD_TYPE}")
MESSAGE(STATUS "With llvm: ${WITH_EXECUTION_ENGINE_LLVM}")
MESSAGE(STATUS "With OpenMP: ${INA_ENABLE_OPENMP}")
MESSAGE(STATUS "With version check: ${INA_ENABLE_VERSION_CHECK}")
MESSAGE(STATUS "With iNA GUI: ${WITH_INA_GUI}")
MESSAGE(STATUS "Static build: ${INA_ENABLE_STATIC}")
MESSAGE(STATUS "Build unit tests: ${INA_BUILD_UNITTEST}")
MESSAGE(STATUS "Compilers C/C++: ${CMAKE_C_COMPILER} / ${CMAKE_CXX_COMPILER}")
MESSAGE(STATUS "C Flags: ${CMAKE_C_FLAGS}")
MESSAGE(STATUS "C++ Flags: ${CMAKE_CXX_FLAGS}")
MESSAGE(STATUS "C++ Flags (debug): ${CMAKE_CXX_FLAGS_DEBUG}")
MESSAGE(STATUS "C++ Flags (release): ${CMAKE_CXX_FLAGS_RELEASE}")
MESSAGE(STATUS "Libraries: ${LIBS}")


#
# Traverse into source tree:
#

add_subdirectory(lib)
#add_subdirectory(unsupported)
#add_subdirectory(cli)

IF(INA_ENABLE_STATIC)
ELSE()
IF(WITH_INA_GUI)
  add_subdirectory(app)
ENDIF(WITH_INA_GUI)
# Exclude unit tests requiring glibc which is not available under Windows!
IF(INA_BUILD_UNITTEST AND NOT WIN32)
  add_subdirectory(test)
ENDIF(INA_BUILD_UNITTEST AND NOT WIN32)
ENDIF(INA_ENABLE_STATIC)

#
# Source distribution packages:
#
set(CPACK_PACKAGE_VERSION_MAJOR "${INA_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${INA_VERSION_MINOR}")
set(CPACK_PACKAGE_VERSION_PATCH "${INA_VERSION_PATCH}")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME
  "${CMAKE_PROJECT_NAME}-${CPACK_PACKAGE_VERSION_MAJOR}.${CPACK_PACKAGE_VERSION_MINOR}.${CPACK_PACKAGE_VERSION_PATCH}")
set(CPACK_SOURCE_IGNORE_FILES
  "/build/;/doc/;/dist/;/.git/;/.svn/;~$;${CPACK_SOURCE_IGNORE_FILES}")
include(CPack)


#
# Install logo and .desktop file under Linux:
#
IF(UNIX AND NOT APPLE)
  INSTALL(FILES shared/IntrinsicNoiseAnalyzer.png
          DESTINATION share/icons)
  INSTALL(FILES shared/IntrinsicNoiseAnalyzer.desktop
          DESTINATION share/applications)
ENDIF(UNIX AND NOT APPLE)


